﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DisplayBoardInfo.Server.Session
{
    /// <summary>
    /// Controls, store and manage current data.
    /// </summary>
    /// <remarks>
    /// Basically this class cares about all data stuffs. For example: creates database, manages data pooling (to not overload database and to faster read nessecery data), resoles data confilcts (ex: when two or more clients edit the same record) and so on.
    /// </remarks>
    public class DataManager
    {
        #region Events

        public event EventHandler StatusChanged;
        public event EventHandler AppointmentsChanged;
        public event EventHandler NextPatient;

        #endregion

        private Entities.User doctor;

        private IEnumerable<Entities.Appointment> appointmentsAll;
        private List<Network.Messages.Content.Appointment> appointments;

        private DateTime date = DateTime.Now;

        private SessionStatus currentStatus;
        private string powod = "";
        private Network.Messages.Content.Patient inRoomPatient;

        public DataManager(Entities.User user)
        {
            this.StatusChanged += new EventHandler(DataManager_StatusChanged);
            this.AppointmentsChanged += new EventHandler(DataManager_AppointmentsChanged);
            this.NextPatient += new EventHandler(DataManager_NextPatient);

            this.doctor = user;
            appointmentsAll = Entities.Appointments.GetByDoctor(user.Username);
            appointments = new List<Network.Messages.Content.Appointment>();
            int a = 1;
            foreach (Entities.Appointment item in appointmentsAll.Where(i => i.DateTime.Year == date.Year && i.DateTime.Month == date.Month && i.DateTime.Day == date.Day).OrderBy(i => i.Number))
            {
                Network.Messages.Content.Appointment app = Helpers.Convert.FromEntityToNetworkEntity(item);
                app.Number = a++;
                appointments.Add(app);
            }
        }

        void DataManager_NextPatient(object sender, EventArgs e)
        {
            if (appointments.Count > 0)
            {
                Network.Messages.Content.Patient next = appointments[0].Patient;
                Helpers.Voice.Read("Do gabinetu wchodzi " + inRoomPatient.Name + " " + inRoomPatient.LastName + ". Następny w kolejce: " + next.Name + " " + next.LastName);
            }
            else
            {
                Helpers.Voice.Read("Do gabinetu wchodzi " + inRoomPatient.Name + " " + inRoomPatient.LastName + ".");
            }
        }

        void DataManager_AppointmentsChanged(object sender, EventArgs e)
        {
            
        }

        void DataManager_StatusChanged(object sender, EventArgs e)
        {
            switch (this.currentStatus)
            {
                case Session.SessionStatus.NiePrzyjmuje:
                    Helpers.Voice.Read("Koniec przyjęć");
                    break;
                case Session.SessionStatus.Przerwa:
                    Helpers.Voice.Read("Przepraszamy, przerwa. " + powod);
                    break;
                case Session.SessionStatus.Przyjmuje:
                    Helpers.Voice.Read("Doktor " + doctor.Name + " " + doctor.LastName + " przyjmuje");
                    break;
            }
        }

        /// <summary>
        /// Gets specyfic collection of appointments
        /// </summary>
        /// <param name="args">Arguments</param>
        /// <returns>Collection of appointments</returns>
        public IEnumerable<Network.Messages.Content.Appointment> GetSpecyficAppointments(Network.Messages.Content.AppointmentArgs args)
        {
            IEnumerable<Entities.Appointment> appointmentsSpec = Entities.Appointments.GetByDoctor(args.ConnectedWithDoctor);
            List<Network.Messages.Content.Appointment> output = new List<Network.Messages.Content.Appointment>();
            foreach (Entities.Appointment item in appointmentsSpec.Where(i => i.DateTime.Year == args.Date.Year && i.DateTime.Month == args.Date.Month && i.DateTime.Day == args.Date.Day).OrderBy(i => i.Number))
            {
                Network.Messages.Content.Appointment app = Helpers.Convert.FromEntityToNetworkEntity(item);
                output.Add(app);
            }

            return output;
        }

        public IEnumerable<Network.Messages.Content.Appointment> Appointments
        {
            get
            {
                return appointments;
            }
            set 
            {
                appointments = new List<Network.Messages.Content.Appointment>(value);
                AppointmentsChanged(this, new EventArgs());
            }
        }

        public Entities.User Doctor
        {
            get { return doctor; }
        }

        public SessionStatus CurrentStatus
        {
            get { return currentStatus; }
            set
            {
                currentStatus = value;

                Thread t = new Thread(delegate()
                {
                    StatusChanged(this, new EventArgs());
                });

                t.SetApartmentState(ApartmentState.STA);
                t.Start();

            }
        }

        public string Powod
        {
            get {
                return powod;
            }
            set {
                powod = value;
            }
        }

        public Network.Messages.Content.Patient InRoomPatient
        {
            get { return inRoomPatient; }
            set 
            { 
                inRoomPatient = value;
                NextPatient(this, new EventArgs());
            }
        }
    }
}
